package evs1.restframework;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Set;

import org.hibernate.AnnotationException;
import org.reflections.Reflections;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;

import com.google.common.base.Predicate;

import evs1.restframework.anno.Evs11Rest;
import evs1.restframework.anno.Evs11Search;
import evs1.restframework.util.AnnotatedClassContainer;

public class AnnotationChecker 
{
	private Reflections reflections;
	private AnnotatedClassContainer classes[];
	
	public AnnotationChecker()
	{ 
		reflections = new Reflections(new ConfigurationBuilder()
			.setUrls(ClasspathHelper.getUrlsForPackagePrefix("evs1"))
			.setScanners(new TypeAnnotationsScanner().filterResultsBy(new RestFilter())));
	}
	
	protected void scanForAnnotations()
	{
		// load annotated classes
		Set<Class<?>> restClasses = reflections.getTypesAnnotatedWith(Evs11Rest.class);
		if(restClasses.size() == 0) 
			throw new AnnotationException("No classes are annotated with @Evs11Service");
		
		// check for invalid annotations
		Iterator<Class<?>> classIterator = restClasses.iterator();
		while(classIterator.hasNext())
		{
			Class<?> theClass = classIterator.next();
			Field[] allFields = theClass.getDeclaredFields();
			for(int i = 0; i < allFields.length; i++)
			{
				Annotation[] allAnnotations = allFields[i].getAnnotations();
				for(int j = 0; j < allAnnotations.length; j++)
				{
					if(allAnnotations[j].annotationType().equals(Evs11Search.class))
					{
						if(!(allFields[i].getType().equals(String.class)))
							throw new AnnotationException("Only String attributes may be annotated with Evs11Search");
					}
				}
			}
		}
		
		this.classes = new AnnotatedClassContainer[restClasses.size()];
		for (int i = 0; i < restClasses.size(); i++)
			this.classes[i] = new AnnotatedClassContainer((Class<?>) restClasses.toArray()[i]);	    
	}
	
   public Class<?> getClassname(String annotatedUrl) 
   {
   	if (annotatedUrl == null)
   		return null;
   	for(int i = 0; i < this.classes.length; i++)   	
   		if (this.classes[i].getDefinedUrl().equals(annotatedUrl))
   			return this.classes[i].getTheClass();
   	return null;
   }
   
   public Field[] getSearchableFields(String annotatedUrl)
   {
   	if (annotatedUrl == null)
   		return null;
   	for(int i = 0; i < this.classes.length; i++)   	
   		if (this.classes[i].getDefinedUrl().equals(annotatedUrl))
   			return this.classes[i].getSearchableFields();
   	return null;
   }
	
	private class RestFilter implements Predicate<String>
	{
		@Override
		public boolean apply(String arg0) {
			if(arg0.equals(Evs11Rest.class.getName()))
				return true;
			return false;
		}
	}
}
